﻿//======================================================================
//
//        Copyright : Zhengzhou Strawberry Computer Technology Co.,LTD.
//        All rights reserved
//        
//        Application:NFinal MVC framework
//        Filename :Frame.cs
//        Description :总框架
//
//        created by Lucas at  2015-6-30`
//     
//        WebSite:http://www.nfinal.com
//
//======================================================================
using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;

namespace NFinal.Compile
{
    /// <summary>
    /// 全局生成类
    /// </summary>
    public class Frame
    {
        /// <summary>
        /// 项目根目录
        /// </summary>
        public static string appRoot;
        /// <summary>
        /// 模块名
        /// </summary>
        public static string AssemblyTitle;
        /// <summary>
        /// 本模块下的连接字符串
        /// </summary>
        public static System.Collections.Generic.List<DB.ConnectionString> ConnectionStrings = new System.Collections.Generic.List<DB.ConnectionString>();

        /// <summary>
        /// 生成类初始化
        /// </summary>
        /// <param name="appRoot">项目根目录</param>
        public Frame(string appRoot)
        {
            Frame.appRoot = appRoot;
            string[] fileNames = Directory.GetFiles(appRoot, "*.csproj");
            if (fileNames.Length > 0)
            {
                AssemblyTitle = Path.GetFileNameWithoutExtension(fileNames[0]);
            }
            else
            {
                string temp;
                temp = appRoot.Trim('\\');
                AssemblyTitle = temp.Substring(temp.LastIndexOf('\\') + 1);
            }
        }

        /// <summary>
        /// 把基于网站根目录的绝对路径改为相对路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string MapPath(string url)
        {
            return appRoot + url.Trim('/').Replace('/', '\\');
        }
        /// <summary>
        /// 释放数据库资源
        /// </summary>
        public void ClearDB()
        {
            if (DB.Coding.DbCache.DbStore.Count > 0)
            {
                foreach (KeyValuePair<string, DB.Coding.DataUtility> da in DB.Coding.DbCache.DbStore)
                {
                    da.Value.con.Close();
                }
                DB.Coding.DbCache.DbStore.Clear();
            }
        }
        /// <summary>
        /// 获取数据库相关数据
        /// </summary>
        /// <param name="config"></param>
        public void GetDB(Config config)
        {
            //获取WebConfig中的连接字符串信息
            Frame.ConnectionStrings.Clear();
            if (config.connectionStrings.Count > 0)
            {
                foreach (DB.ConnectionString connectionString in config.connectionStrings)
                {
                    if (connectionString.provider.ToLower().IndexOf("mysql") > -1)
                    {
                        connectionString.type = DB.DBType.MySql;
                    }
                    else if (connectionString.provider.ToLower().IndexOf("sqlclient") > -1)
                    {
                        connectionString.type = DB.DBType.SqlServer;
                    }
                    else if (connectionString.provider.ToLower().IndexOf("sqlite") > -1)
                    {
                        connectionString.type = DB.DBType.Sqlite;
                    }
                    else if (connectionString.provider.ToLower().IndexOf("oracle") > -1)
                    {
                        connectionString.type = DB.DBType.Oracle;
                    }
                    else if (connectionString.provider.ToLower().IndexOf("npgsql") > -1)
                    {
                        connectionString.type = DB.DBType.PostgreSql;
                    }
                    Frame.ConnectionStrings.Add(connectionString);
                }
            }
            //读取数据库信息
            DB.Coding.DataUtility dataUtility = null;
            if (Frame.ConnectionStrings.Count > 0)
            {
                DB.ConnectionString conStr;
                DB.Coding.DbCache.DbStore.Clear();
                for (int i = 0; i < Frame.ConnectionStrings.Count; i++)
                {
                    conStr = Frame.ConnectionStrings[i];
                    if (conStr.type == DB.DBType.MySql)
                    {
                        dataUtility = new DB.Coding.MySQLDataUtility(conStr.value);
                        dataUtility.GetAllTables(dataUtility.con.Database);
                        DB.Coding.DbCache.DbStore.Add(conStr.name, dataUtility);
                    }
                    else if (conStr.type == DB.DBType.Sqlite)
                    {
                        dataUtility = new DB.Coding.SQLiteDataUtility(conStr.value);
                        dataUtility.GetAllTables(dataUtility.con.Database);
                        DB.Coding.DbCache.DbStore.Add(conStr.name, dataUtility);
                    }
                    else if (conStr.type == DB.DBType.SqlServer)
                    {
                        dataUtility = new DB.Coding.SQLDataUtility(conStr.value);
                        dataUtility.GetAllTables(dataUtility.con.Database);
                        DB.Coding.DbCache.DbStore.Add(conStr.name, dataUtility);
                    }
                    else if (conStr.type == DB.DBType.Oracle)
                    {
                        dataUtility = new DB.Coding.OracleDataUtility(conStr.value);
                        dataUtility.GetAllTables(dataUtility.con.Database);
                        DB.Coding.DbCache.DbStore.Add(conStr.name, dataUtility);
                    }
                    else if (conStr.type == DB.DBType.PostgreSql)
                    {
                        dataUtility = new DB.Coding.PostgreSqlDataUtility(conStr.value);
                        dataUtility.GetAllTables(dataUtility.con.Database);
                        DB.Coding.DbCache.DbStore.Add(conStr.name, dataUtility);
                    }
                }
            }
        }

        /// <summary>
        /// 获取所有的应用模块
        /// </summary>
        /// <returns>模块名数组</returns>
        public string[] GetApps()
        {
            string[] dirs = Directory.GetDirectories(MapPath("/"));
            string configJsonFileName = string.Empty;
            System.Collections.Generic.List<string> apps = new System.Collections.Generic.List<string>();
            for (int i = 0; i < dirs.Length; i++)
            {
                configJsonFileName = System.IO.Path.Combine(dirs[i], "config.json");
                if (File.Exists(configJsonFileName))
                {
                    apps.Add(System.IO.Path.GetFileName(dirs[i]));
                }
            }
            return apps.ToArray();
        }
        /// <summary>
        /// 获取所有的控制器
        /// </summary>
        /// <returns>所有的控制器</returns>
        public System.Collections.Generic.List<ControllerFileData> GetAllControllers()
        {
            string[] apps = GetApps();
            System.Collections.Generic.List<ControllerFileData> fileDataList = new System.Collections.Generic.List<ControllerFileData>();
            ControllerAnalyse com = new ControllerAnalyse();
            ControllerFileData fileData = null;
            string[] fileNames = null;
            string controllerPath = string.Empty;
            Config config = null;
            for (int i = 0; i < apps.Length; i++)
            {
                controllerPath = Frame.MapPath("/" + apps[i].Trim('/') + "/Controllers");
                if (!Directory.Exists(controllerPath))
                {
                    continue;
                }
                fileNames = Directory.GetFiles(controllerPath, "*.cs", SearchOption.AllDirectories);
                if (fileNames == null || fileNames.Length < 1)
                {
                    continue;
                }
                config = ConfigurationManager.GetConfig(apps[i], Frame.appRoot);
                for (int j = 0; j < fileNames.Length; j++)
                {
                    fileData = com.GetFileData(Frame.appRoot, apps[i], fileNames[j], System.Text.Encoding.UTF8, config);
                    fileDataList.Add(fileData);
                }
            }
            return fileDataList;
        }
        /// <summary>
        /// 找到ActionURL
        /// </summary>
        /// <param name="controllerFileDataList">控制器实体类</param>
        /// <param name="rewriteData">重写配置数据</param>
        public void CreateActionSearch(System.Collections.Generic.List<ControllerFileData> controllerFileDataList, ReWriteData rewriteData)
        {
            JinianNet.JNTemplate.ITemplate template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.NFinal.NFinal.ActionSearch));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Render(MapPath("/App_Start/NFinal/ActionSearch.cs"), System.Text.Encoding.UTF8);
        }
        /// <summary>
        /// 创建middleware中间件，用于移值。
        /// </summary>
        /// <param name="controllerFileDataList">控制器实体类</param>
        /// <param name="rewriteData">重写配置数据</param>
        public void CreateOwinMiddlewareAndRouter(System.Collections.Generic.List<ControllerFileData> controllerFileDataList, ReWriteData rewriteData)
        {
            JinianNet.JNTemplate.ITemplate template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.NFinal.NFinal.Middleware));
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/App_Start/NFinal/Middleware.cs"), System.Text.Encoding.UTF8);
            template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.Startup.OwinRouter));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/App_Start/OwinRouter.cs"), System.Text.Encoding.UTF8);
        }
        /// <summary>
        /// URL解析
        /// </summary>
        /// <param name="controllerFileDataList">控制器实体类</param>
        /// <param name="rewriteData">重写配置数据</param>
        public void CreateModuleAndRouter(System.Collections.Generic.List<ControllerFileData> controllerFileDataList,ReWriteData rewriteData)
        {
            JinianNet.JNTemplate.ITemplate template= new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.NFinal.NFinal.Module));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Render(MapPath("/App_Start/NFinal/Module.cs"), System.Text.Encoding.UTF8);
            template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.NFinal.NFinal.Handler));
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/App_Start/NFinal/Handler.cs"), System.Text.Encoding.UTF8);
            template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.Startup.Router));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/App_Start/Router.cs"),System.Text.Encoding.UTF8);
        }
        /// <summary>
        /// URL生成
        /// </summary>
        /// <param name="controllerFileDataList">控制器实体类</param>
        /// <param name="rewriteData">重写配置数据</param>
        public void CreateURLHelper(System.Collections.Generic.List<ControllerFileData> controllerFileDataList, ReWriteData rewriteData)
        {
            JinianNet.JNTemplate.ITemplate template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Startup.Startup.Url));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/App_Start/Url.cs"), System.Text.Encoding.UTF8);
            template = new JinianNet.JNTemplate.Template(
                System.Text.Encoding.UTF8.GetString(NFinal.Compile.Template.Scripts.Scripts.Url_Js));
            template.Context.TempData["controllerFileDataList"] = controllerFileDataList;
            template.Context.TempData["rewriteData"] = rewriteData;
            template.Context.TempData["project"] = Frame.AssemblyTitle;
            template.Render(MapPath("/Scripts/Url.js"), System.Text.Encoding.UTF8);
        }
    }

}